#ifndef __OPTSRC_HPP__
#define __OPTSRC_HPP__

/* =========== Control PD2-6024-4&6-LS =========== */

#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<termios.h>

#include<cerrno>
#include<cstdio>
#include<cstdlib>
static int global_optsrc_counter_xxx = 0;
static int global_optsrc_fdUsbPort = -1;
class optsrc {
    private:
        int cmdon_length = 7;
        unsigned char cmdon[7] = { 0x40, 0x05, 0x01, 0x00, 0x2A, 0xFF, 0x01 };
        int cmdoff_length = 7;
        unsigned char cmdoff[7] = { 0x40, 0x05, 0x01, 0x00, 0x2A, 0xFF, 0x00 };

        ssize_t writen(int fd, const void *vptr, size_t n) {
            /* Write "n" bytes to a descriptor. */
            size_t		nleft;
            ssize_t		nwritten;
            const char	*ptr;

            ptr = (const char *)vptr;
            nleft = n;
            while (nleft > 0) {
                if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
                    if (nwritten < 0 && errno == EINTR)
                        nwritten = 0;		/* and call write() again */
                    else
                        return(-1);			/* error */
                }

                nleft -= nwritten;
                ptr   += nwritten;
            }
            return(n);
        }

        void errno_exit(const char *s) {
            perror(s);
            exit(EXIT_FAILURE);
        }

        int usbPortWrite(const unsigned char *cmd, int length) {
            unsigned char verify = 0;
            int i;
            if(global_optsrc_fdUsbPort == -1)
                return -1;

            for(i = 0; i < length; i++) {
                writen(global_optsrc_fdUsbPort, &cmd[i], sizeof(char));
                verify += cmd[i];
            }
            writen(global_optsrc_fdUsbPort, &verify, sizeof(char));
            tcflush(global_optsrc_fdUsbPort, TCOFLUSH);
            return 0;
        }

    public:
        optsrc(const char *dev_name = "/dev/ttyUSB0") {
            int ret;
            if(global_optsrc_counter_xxx > 0)
                return;

            global_optsrc_fdUsbPort = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
            if(global_optsrc_fdUsbPort == -1)
                errno_exit("failed to open tty\n");

            tcflush(global_optsrc_fdUsbPort, TCIOFLUSH);
            struct termios portAttr;
            tcgetattr(global_optsrc_fdUsbPort, &portAttr);
            cfsetispeed(&portAttr,B19200);
            cfsetospeed(&portAttr,B19200);
            ret = tcsetattr(global_optsrc_fdUsbPort, TCSANOW, &portAttr);
            if(ret < 0)
                errno_exit("tcsetattr() failed to set the attr");
            global_optsrc_counter_xxx++;
        }

        ~optsrc() {
            global_optsrc_counter_xxx--;
            if(global_optsrc_counter_xxx > 0)
                return;
            close(global_optsrc_fdUsbPort);
        }

        int Allon(void) {
            return usbPortWrite(cmdon, cmdon_length);
        }

        int Alloff(void) {
            return usbPortWrite(cmdoff, cmdoff_length);
        }

        int Write(const unsigned char *cmd, int length) {
            return usbPortWrite(cmd, length);
        }
};
#endif
